package com.chs.recoginition.core.utils;

import com.chs.recoginition.core.enums.Base64FileTypeEnum;
import com.chs.recoginition.core.utils.baidu.Base64Util;
import com.chs.recoginition.core.utils.baidu.FileUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.chs.recoginition.core.utils.UploadUtil.getRootPath;

/**
 * 图片转换工具类
 * @Author CHS
 * @Date 2023/3/7 21:36
 * @Version 1.0
 **/
public class FileAndBaseUtils {
    /**
     * 指定压缩后长宽
     * @param originalImage
     * @param targetWidth
     * @param targetHeight
     * @return
     * @throws IOException
     */
    public static BufferedImage resizeImage(BufferedImage originalImage, int targetWidth, int targetHeight) throws IOException {
        Image resultingImage = originalImage.getScaledInstance(targetWidth, targetHeight, Image.SCALE_AREA_AVERAGING);
        BufferedImage outputImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
        outputImage.getGraphics().drawImage(resultingImage, 0, 0, null);
        return outputImage;
    }

    /**
     * 缩小倍数
     * @param originalImage
     * @param reduceMultiple
     * @return
     * @throws IOException
     */
    public static BufferedImage resizeImage(BufferedImage originalImage, float reduceMultiple) throws IOException {
        int width = (int) (originalImage.getWidth() * reduceMultiple);
        int height = (int) (originalImage.getHeight() * reduceMultiple);
        Image resultingImage = originalImage.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING);
        BufferedImage outputImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        outputImage.getGraphics().drawImage(resultingImage, 0, 0, null);
        return outputImage;
    }


    /**
     * 每次压缩比率
     * @param srcImgData
     * @param reduceMultiple
     * @return
     * @throws IOException
     */
    public static byte[] resizeImage(byte[] srcImgData, float reduceMultiple) throws IOException {
        BufferedImage bi = ImageIO.read(new ByteArrayInputStream(srcImgData));
        int width = (int) (bi.getWidth() * reduceMultiple); // 源图宽度
        int height = (int) (bi.getHeight() * reduceMultiple); // 源图高度
        Image image = bi.getScaledInstance(width, height, Image.SCALE_SMOOTH);
        BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = tag.getGraphics();
        g.setColor(Color.RED);
        g.drawImage(image, 0, 0, null); // 绘制处理后的图
        g.dispose();
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        ImageIO.write(tag, "JPEG", bOut);
        return bOut.toByteArray();
    }


    /**
     * BufferedImage图片流转byte[]数组
     * @param bImage
     * @return
     */
    public static byte[] imageToBytes(BufferedImage bImage) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bImage, "jpg", out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }


    /**
     * byte[]数组转BufferedImage图片流
     * @param ImageByte
     * @return
     */
    public static BufferedImage bytesToBufferedImage(byte[] ImageByte) {
        ByteArrayInputStream in = new ByteArrayInputStream(ImageByte);
        BufferedImage image = null;
        try {
            image = ImageIO.read(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return image;
    }


    /**
     * 图片转成base64
     * @param image
     * @param type
     * @return
     */
    public static String encodeToString(BufferedImage image, String type) {

        String imageString = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {
            ImageIO.write(image, type, bos);
            byte[] imageBytes = bos.toByteArray();

            BASE64Encoder encoder = new BASE64Encoder();
            imageString = encoder.encode(imageBytes);

            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imageString;
    }


    /**
     * BASE64解码成File文件
     * @param base64
     * @return
     */
    public static Map<String,Object> base64ToFile(String base64, String savePath, String fileName) {
        Map<String,Object> result = new HashMap<>();
        File file = null;
        String path = "";
        //创建文件目录
        String rootPath = getRootPath();
        String dirPath = rootPath + savePath;
        File dir=new File(dirPath);
        if (!dir.exists() && !dir.isDirectory()) {
            dir.mkdirs();
        }
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        try {


            //截取base64头部，获取文件类型
//            String fileType = Base64FileTypeEnum.getFileType(base64.substring(0, base64.indexOf(",")));
//            String fileType = null;
            String fileType = "jpg";
            //去掉头部，防止转换文件后打开显示文件损坏
            String s = base64.substring(base64.indexOf(",")+1);
            byte[] bytes = new BASE64Decoder().decodeBuffer(s);
            path = savePath+"/" + fileName + LocalDateTimeUtils.format(new Date(), "yyyyMMddHHmmss") + "." + fileType;
            file=new File(rootPath+path);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        result.put("file",file);
        result.put("path",path);
        return result;
    }

    /**
     * File转MultipartFile
     * @param file
     * @return
     */
    public static MultipartFile getMultipartFile(File file) {
        FileItem item = new DiskFileItemFactory().createItem("file"
                , MediaType.MULTIPART_FORM_DATA_VALUE
                , true
                , file.getName());
        try (InputStream input = new FileInputStream(file);
             OutputStream os = item.getOutputStream()) {
            // 流转移
            IOUtils.copy(input, os);
        } catch (Exception e) {
            throw new IllegalArgumentException("Invalid file: " + e, e);
        }

        return new CommonsMultipartFile(item);
    }


//    public static void main(String[] args) throws IOException {
//        String base = imageUrlToBase64("http://localhost:18081/imageRecognition/images/baidu/auto20230404000005.jpg");
//        BufferedImage multipartFile = base64ToBufferedImage(base);
//            // 压缩到小于指定文件大小1m
//            double targetSize = 128 * 1024;
//        BufferedImage bufferedImage = resizeImage(multipartFile, 800, 800);
//        String jpg = encodeToString(bufferedImage, "JPG");
//        System.out.println(jpg);
//
//    }
    /**
     * 图片URL转Base64编码
     * @param imgUrl 图片URL
     * @return Base64编码
     */
    public static String imageUrlToBase64(String imgUrl) {
        URL url = null;
        InputStream is = null;
        ByteArrayOutputStream outStream = null;
        HttpURLConnection httpUrl = null;

        try {
            url = new URL(imgUrl);
            httpUrl = (HttpURLConnection) url.openConnection();
            httpUrl.connect();
            httpUrl.getInputStream();

            is = httpUrl.getInputStream();
            outStream = new ByteArrayOutputStream();

            //创建一个Buffer字符串
            byte[] buffer = new byte[1024];
            //每次读取的字符串长度，如果为-1，代表全部读取完毕
            int len = 0;
            //使用输入流从buffer里把数据读取出来
            while( (len = is.read(buffer)) != -1 ){
                //用输出流往buffer里写入数据，中间参数代表从哪个位置开始读，len代表读取的长度
                outStream.write(buffer, 0, len);
            }

            // 对字节数组Base64编码 "data:image/jpeg;base64,"
            return encode(outStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(is != null) {
                    is.close();
                }
                if(outStream != null) {
                    outStream.close();
                }
                if(httpUrl != null) {
                    httpUrl.disconnect();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return null;
    }

    /**
     * 图片转字符串
     * @param image 图片Buffer
     * @return Base64编码
     */
    public static String encode(byte[] image){
        BASE64Encoder decoder = new BASE64Encoder();
        return replaceEnter(decoder.encode(image));
    }

    /**
     * 字符替换
     * @param str 字符串
     * @return 替换后的字符串
     */
    public static String replaceEnter(String str){
        String reg ="[\n-\r]";
        Pattern p = Pattern.compile(reg);
        Matcher m = p.matcher(str);
        return m.replaceAll("");
    }

    /**
     * base64 编码转换为 BufferedImage
     * @param base64
     * @return
     */
    public  static BufferedImage base64ToBufferedImage(String base64) {
        Base64.Decoder decoder = Base64.getDecoder();
//        BASE64Decoder decoder = new sun.misc.BASE64Decoder();
        try {
            byte[] bytes1 = decoder.decode(base64);
            ByteArrayInputStream bais = new ByteArrayInputStream(bytes1);
            return ImageIO.read(bais);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
